// strngbad.cpp -- StringBad class methods
#include <cstring>                    // string.h for some
#include "strngbad.h"
#include <iostream>

using std::cout;

// initializing static class member
int StringBad::num_strings = 0;

// class methods

// construct StringBad from C string
StringBad::StringBad(const char *s) {
    len = std::strlen(s);             // set size
    str = new char[len + 1];          // allot storage
    std::strcpy(str, s);              // initialize pointer
    num_strings++;                    // set object count
    cout << num_strings << ": \"" << str
         << "\" 对象已创建 created\n";    // For Your Information
}

StringBad::StringBad()                // default constructor
{
    len = 4;
    str = new char[4];
    std::strcpy(str, "C++");          // default string
    num_strings++;
    cout << num_strings << ": \"" << str
         << "\" 默认对象已被创建 created\n";  // FYI
}

StringBad::~StringBad()               // necessary destructor
{
    cout << "\"" << str << "\" object deleted, ";    // FYI
    --num_strings;                    // required
    cout << num_strings << " left\n"; // FYI
    delete[] str;                    // required
}

std::ostream &operator<<(std::ostream &os, const StringBad &st) {
    os << st.str << std::endl;
    return os;
}

// 复制构造函数不需要返回值
StringBad::StringBad(const StringBad &old) {
    const char *s = old.str;
    num_strings++;
    cout << "复制构造函数被调用，正在复制：" << s << std::endl;
    int max_len = old.len + 1;
    str = new char[max_len];
    std::strcpy(str, old.str);
    str[max_len - 1] = '\0';
    len = old.len;
//    return StringBad(s);
}

/*
 * 重载赋值运算符
 * 此处是以 被赋值（等号左边的操作数）为对象来调用 赋值运算符（=）的
 * 赋值运算符右边（等号右边的操作数）将作为参数（old）传入此方法
 */
StringBad &StringBad::operator=(const StringBad &old) {

    if (this == &old) {
//        检查是不是将自己赋值给自己 a=a
        return *this;
    }

    const char *old_str_p = old.str;
//    num_strings++; // 赋值操作并不会创建新的对象
    cout << "重载赋值运算符，正在赋值：" << old_str_p << std::endl;
    int max_len = old.len + 1;

//    1、释放此前可能已经占用的内存，（如果指针为空，则delete不会引发异常）
    delete str;

    /*this -> */str = new char[max_len];

//    使用深拷贝
    std::strcpy(str, old_str_p);
    str[max_len - 1] = '\0';

    len = old.len;

//    此处返回的是赋值运算符的结果，即 (a = b)
//      返回一个指向调用对象的引用，可以继续赋值
    return *this;
}


//    重载 >> 运算符，搭配 istream 使用
std::istream &operator>>(std::istream &in, StringBad &sb) {
    using namespace std;
    delete sb.str;
    int max_size = 10;

//    可以不使用 new 关键字，而改用声明 char[] ，然后使用 = 赋值操作符，因为经历多次拷贝，性能不高

//  手动删除 并重新赋值，效率高
    sb.str = new char[max_size];
    in.get(sb.str, max_size);
    return in;
}


//    从 StringBad 中取出第i个 字符
char &StringBad::operator[](const int i) {

    return this->str[i];
}

const char &StringBad::operator[](const int i) const {
    return str[i];
}

int StringBad::size() const {
    return strlen(str);
}

int StringBad::HowMany() {
    return num_strings;
}

int StringBad::operator>(const StringBad &second) const {

    for (int i = 0; i < size(); ++i) {


        if (i > second.size()) {
            return 1;
        }
        if (str[i] == second.str[i]) {
            continue;
        }

        if (str[i] > second.str[i]) {
            return 1;
        } else {
            return 0;
        }
    }
//    if(second.size()>=size()){
    return 0;
//    }
}

int StringBad::operator<(const StringBad &second) const {
    return second > *this  ;
}